# 导包
import hashlib
import json
import re
from datetime import tzinfo
from functools import wraps
from operator import mod
from os import write

import requests
from peewee import EXCEPTIONS, NoopModelSelect
from redis.client import Redis
import tornado.web

from bson.objectid import ObjectId

# 服务器
from tornado import httpserver
from werkzeug.datastructures import Headers

# 导入基础类
from base import BaseHandler, WsBaseHandler

# 导入数据库操作类
from db import *

from tools import ret_json, Chat, ACL, RBAC, ABAC, BinAuth, OrderQueue, table_size, clear_last

import jwt, os

# 导入栈列
from test_stack import MyStack

# python内置装饰器库
from functools import wraps

# 导入队列类mysql                    mongo
from test_queue import ChatQueue, MyQueueSort, MyMongo_QueueSort, RedisQueue, MysqlDb, get_queue, DelayRedisQueue

# 导入多线程队列
from out_queue import doout
import threading

import random

import redis

# 导入分页类
from mypage import Page

# 密->明    明->密  双向
import base64

from pay import AliPay

# 导入实例
from user_view import get_ali_pay

# 导入redis分布式锁           # 上锁            # 释放锁
from test_setnx import distributed_lockup, distributed_release_locks

# 字典中央控制
manage_dict = {1: Order_1, 2: Order_2, 3: Order_3}
# manage_dict = {1: 'Order_1', 2: 'Order_2', 3: 'Order_3'}

# 退款请求接口
r = redis.Redis(decode_responses=True)


class RefundMoney(BaseHandler):

    # 退款请求
    async def get(self):
        # 接收参数
        refund_amount = self.get_argument('price', None)
        out_trade_no = self.get_argument('orderid',None)

        uid = self.get_argument('uid', None)

        # 取模运算
        table_num = hash(int(out_trade_no) % 3) + 1

        # order = await self.application.objects.get(
        #     manage_dict[table_num].select().where(manage_dict[table_num].orderid == out_trade_no))
        # order = await self.application.objects.get(manage_dict[table_num],manage_dict[table_num].orderid == out_trade_no)
        order = await self.application.objects.get(
            manage_dict[table_num].select().where(manage_dict[table_num].orderid == out_trade_no))

        # mysql = MysqlDb()
        # order = mysql.read("select * from Order_%s where orderid = %s" % (table_num,out_trade_no))

        # print(order)

        if order.price < int(refund_amount):
            return self.write(ret_json({'code': 403, 'meg': '退款金额不能大于订单金额!'}))

        # 查询此人钱包
        user = await self.application.objects.get(User.select().where(User.id == uid))
        if user.wallet < int(refund_amount):
            return self.write(ret_json({'code': 403, 'meg': '此用户钱包资金不足!'}))

        # 加锁
        if distributed_lockup(out_trade_no) == 1:
            try:

                # 查询该充值订单,此前有没有退款
                reorders = await self.application.objects.execute(Refund.select().where(Refund.orderid == out_trade_no))

                # print(reorders)

                reorders = [myser(x) for x in reorders]

                # print(reorders)

                if not reorders:
                    if int(refund_amount) > order.price:
                        return self.write(ret_json({'code': 403, 'meg': "退款金额不能大于订单金额"}))
                # 非首次
                else:
                    # 累加退款金额
                    total = 0
                    for i in reorders:
                        total += i['price']
                    # print(total)

                    # 支付金额 - 历史退款总金额
                    limit_price = order.price - total

                    if int(refund_amount) > limit_price:
                        return self.write(ret_json({'code': 403, 'meg': '退款金额不能大于订单金额'}))

                # 退单记录
                await self.application.objects.create(Refund, orderid=out_trade_no, price=refund_amount)

                print('退款记录+++++++++++++++')

                # 累加充值金额
                user.wallet -= int(refund_amount)

                # 异步修改
                await self.application.objects.update(user)

                # 实例化操作
                alipay = get_ali_pay()

                # 发起退款请求
                res = alipay.api_alipay_refund(out_trade_no=out_trade_no,
                                               refund_amount=refund_amount, notify_url="https://localhost/refund_back/")

                return self.write(ret_json({'code': 200, 'meg': '退款成功'}))

            except Exception as e:
                print(e)

            finally:

                distributed_release_locks(out_trade_no)
